#!env/bin/python
import logging
import asyncio
from aiogram import Bot, Dispatcher, executor, types, utils
from sys import exit

from aiogram.types.chat import Chat
from app.helpers import replacer
from app.messages_templates import message_with_events, start_help_message, cant_create_message
from app.data_provider import check_notifications_now, delete_meeting_and_notifications, get_all_users_meetings

from app.event import handle_event_message
from config.config import BOT_TOKEN
from app.buttons import create_yes_no_btns, events_kb


if not BOT_TOKEN:
    exit("Error: no token provided")

try:
    bot = Bot(token=BOT_TOKEN, parse_mode=types.message.ParseMode.MARKDOWN_V2)
except utils.exceptions.ValidationError:
    exit("Произошла ошибка валидации токена. Возможно, вам нужно указать \
правильный бот токен в переменных окружения.\n=== Завершение программы ===")

dp = Dispatcher(bot)
logging.basicConfig(level=logging.INFO)

async def check_if_user_can_create_event(message: types.Message) -> bool:
    """
    Проверяет может ли пользователь создавать мероприятия в этом чате
    Доступно только в группе и только для админов группы. Возвращает
    правду или ложь
    """
    chat_member = await message.chat.get_member(message.from_user.id)
    return True if chat_member.status == "creator" or chat_member.status\
             == "administrator" else False
    
async def get_chat_title(chat_id: int) -> Chat:
    return await bot.get_chat(chat_id=chat_id)

async def check_time_and_send_message(sleep_for):
    """
    Проверяет с определенным промежутком есть ли напоминания в данное время
    Делает рассылку напоминаний по чатам, если на это время есть напоминание
    """
    while True:
        await asyncio.sleep(sleep_for)
        notifications = check_notifications_now()
        for n in notifications:
            await bot.send_message(n["chat_id"], n["message"])


@dp.message_handler(commands=["start", "help"])
async def start_help(message: types.Message):
    """Обратаывает команды start help. Присылает инструкцию"""
    buttons = events_kb if message.from_user.id == message.chat.id else None
    await message.reply(
            start_help_message.format(bot_username=replacer(bot._me.username)),
            reply_markup=buttons)



@dp.message_handler(lambda message: message.text.lower().startswith('встреча+'))
async def event(message: types.Message):
    """
    Принимает, проверяет команду создания мероприятия. Отпраляет ошибку ввода
    или уведомление о созданном мероприятии
    """
    if not await check_if_user_can_create_event(message):
        return await message.answer(cant_create_message)
    try:
        message_now = handle_event_message(message)
    except ValueError as error:
        return await message.answer("Ошибка ввода данных: " + error.args[0])
    await message.answer(message_now)

@dp.message_handler(
        lambda message: message.text == events_kb.keyboard[0][0].text\
        and message.from_user.id == message.chat.id)
async def get_my_events(message: types.Message):
    """
    При запросе в чат с ботом с текстом -Мои мероприятия- или по кнопке
    функция отправит сообщение со всеми актуальными встречами, которые
    можно отменить
    """
    meetings = get_all_users_meetings(message.from_user.id)
    for i in range(len(meetings)):
        chat = await get_chat_title(meetings[i]["chat_id"])
        meetings[i]["chat_title"] =  chat.title
    await message.reply(message_with_events(meetings))

@dp.message_handler(lambda message: message.text.lower().startswith('/delete_'))
async def delete_event(message: types.Message):
    await message.reply(
            "Вы уверены, что хотите отменить встречу и удалить напоминания?",
            reply_markup=create_yes_no_btns(message.text))

@dp.callback_query_handler(lambda c: c.data == 'cancel')
async def process_callback_cancel(callback_query: types.CallbackQuery):
    """Обрабатываем кнопку отмены. Ничего не делаем, просто посылаем ответ"""
    await bot.answer_callback_query(
            callback_query.id,
            text="Ура! Ничего не отменяем")
    await bot.delete_message(
            chat_id=callback_query.message.chat.id,
            message_id=callback_query.message.message_id)


@dp.callback_query_handler(lambda c: c.data and c.data.startswith('/delete_'))
async def process_callback_button2(callback_query: types.CallbackQuery):
    """
    Обрабатываем кнопку подтверждения удаления
    """
    user_id = callback_query.from_user.id
    meeting_id: int = int(callback_query.data[8:])
    await bot.delete_message(
            chat_id=callback_query.message.chat.id,
            message_id=callback_query.message.message_id)
    await bot.answer_callback_query(callback_query.id)
    try:
        delete_meeting_and_notifications(meeting_id, user_id)
    except Exception as error:
        return await bot.send_message(user_id, error.args[0])
    await bot.send_message(
            user_id, f'Встреча и все напоминания о ней были удалены\.')

if __name__ == "__main__":
    print(f"Bot has been started...")
    loop = asyncio.get_event_loop()
    loop.create_task(check_time_and_send_message(60))
    executor.start_polling(dp, skip_updates=True)
